package com.tl.boot.async;


import com.alibaba.fastjson.JSONObject;
import com.tl.boot.common.constants.CommonConstant;
import com.tl.boot.common.utils.CollectionUtil;
import com.tl.boot.common.utils.LogUtil;
import com.tl.boot.common.utils.PermissionUtil;
import com.tl.boot.entity.login.dto.LoginRecordDTO;
import com.tl.boot.entity.menu.domain.MenuAfterLoginInfo;
import com.tl.boot.entity.permission.vo.PermissionInfoVO;
import com.tl.boot.service.menu.MenuService;
import com.tl.boot.service.user.SysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


/**
 * com.tl.boot.main.hanlder -- LocalAsyncHandler
 * Description:
 * Created by joshua_liu <a href="mailto:joshualwork@163.com"></a>
 * On 2019/9/12 9:28
 */
@Component
public class LocalAsyncHandler {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private MenuService menuService;

    @Async
    public void storeUserPermissionInfo(Long userId) {
        LogUtil.info(String.format("start store user permission info>>>userId[%s]", userId));
        try {
            if (PermissionUtil.getPermissionInfo(userId) != null) {
                //先判断redis中是否已经有了用户的权限信息，
                return;
            } else {
                // 没有的话从数据库获取用户权限信息
                List<PermissionInfoVO> list = sysUserService.getPermissionInfo(userId);
                List<MenuAfterLoginInfo> menuAfterLoginInfoList = CollectionUtil.
                        removeDuplicate(list.stream().map(e -> {
                            MenuAfterLoginInfo m = new MenuAfterLoginInfo();
                            BeanUtils.copyProperties(e, m);
                            return m;
                        }).collect(Collectors.toList()));
                //获取到所有的菜单id
                getParentMenuList(menuAfterLoginInfoList, null);
                List<Long> resultMenuIds = menuAfterLoginInfoList.stream().
                        map(MenuAfterLoginInfo::getMenuId).
                        collect(Collectors.toList());
                List<Long> hasPermissionIds = list.stream().
                        map(PermissionInfoVO::getResId).
                        collect(Collectors.toList());
                //通过菜单id列表再去获取菜单的所有资源信息
                menuAfterLoginInfoList = menuService.queryMenuAfterLoginInfo(resultMenuIds,hasPermissionIds);
                //将用户动态菜单信息存储进redis
                List<String> roleInfos =
                        list.stream().map(PermissionInfoVO::getRoleCode).
                                collect(Collectors.toList());
                roleInfos = CollectionUtil.removeDuplicate(roleInfos);
                List<String> resourceInfos =
                        list.stream().map(PermissionInfoVO::getResUrl).
                                collect(Collectors.toList());
                resourceInfos = CollectionUtil.removeDuplicate(resourceInfos);
                JSONObject permissionInfo = new JSONObject();
                permissionInfo.put(CommonConstant.ROLE_LIST, roleInfos);
                permissionInfo.put(CommonConstant.ROSOURCE_LIST, resourceInfos);
                permissionInfo.put(CommonConstant.MENU_INFO_LIST, menuAfterLoginInfoList);
                PermissionUtil.setEncryptPermissionInfo(userId, permissionInfo);
            }
        } catch (Exception e) {
            LogUtil.error(e);
        }
    }

    @Async
    @Transactional(rollbackFor = Exception.class,transactionManager = "dynamicTxManager")
    public void addLoginRecord(LoginRecordDTO dto) {
        LogUtil.info(String.format("start insert login record>>>userIfo[%s]", JSONObject.toJSONString(dto)));
        sysUserService.addLoginRecord(dto);
        //添加登录记录
    }

    private void getParentMenuList(List<MenuAfterLoginInfo> menuAfterLoginInfos, List<MenuAfterLoginInfo> parentMenuInfos) {
        //获取所有父节点id
        List<Long> parentIds = new ArrayList<>();
        for (MenuAfterLoginInfo e : menuAfterLoginInfos) {
            if (e.getParentMenuId() != 0) {
                parentIds.add(e.getParentMenuId());
            }
        }
        //去除已经查出菜单的所有id
        parentIds.removeAll(
                menuAfterLoginInfos.stream().map(MenuAfterLoginInfo::getMenuId).
                        collect(Collectors.toList()));
        parentIds = CollectionUtil.removeDuplicate(parentIds);

        // 如果父节点列表去重后不为空
        if (parentIds.size() > 0) {
            //查出所有父节点，
            parentMenuInfos = menuService.parentMenuInfos(parentIds);
            //去重，
            parentMenuInfos = CollectionUtil.removeDuplicate(parentMenuInfos);
            //添加进原列表
            menuAfterLoginInfos.addAll(parentMenuInfos);
            //，递归
            getParentMenuList(menuAfterLoginInfos, parentMenuInfos);
        }
    }


}
